package com.mq.simple;

import com.mq.config.ConnectUtils;
import com.rabbitmq.client.*;

import java.io.IOException;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeoutException;

/**
 * @Author hezhaoxiang
 * @Description //手动确认消息接收
 * 手动确认消息接收 可以在监听函数 handleDelivery 中处理复杂业务操作时，保证业务的 “原子性”
 * “原子性” - （即操作途中异常，消息也不会被消费）
 * 在处理消息时，消息的状态是 unacked（已接收，未确认）
 *  业务处理报异常，消息状态则会 unacked -> Ready
 * @Date 14:37 2020/9/6
 **/
public class HelloWorldRec2 {

    private final static String QUEUE_NAME = "HELLO";

    public static void recMsg() throws URISyntaxException, KeyManagementException, TimeoutException, NoSuchAlgorithmException, IOException {
        //1. 获取连接
        Connection connect = ConnectUtils.getConnect();
        //2. 获取通道
        Channel channel = connect.createChannel();
        //3. 创建/获取 队列(如果队列不存在，则创建，反之则直接，参数要与生产者一致)
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        //4. 接收消息
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            //接收消息，并且处理，这个方法类似事件监听，如果有消息的时候，会被自动调用
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String msg = new String(body, "UTF-8");
                System.out.println("msg:" + msg);
                //4.1 手动确认消息接收
                //第二个参数 是否确认全部消息，false 只确认当前消息 true 全部消息都确认接收
                channel.basicAck(envelope.getDeliveryTag(),false);
            }

        };
        //5. 确认消息（监听队列，第二个参数    是否自动进行消息确认）
        //如果上式监听函数 handleDelivery 中开启了手动确认接收，则此处 自动进行消息确认就需要设置成 false
        //此时 通道和连接不用关闭，会持续接收消息，当生产者生产消息后，自动调用上方法，显示
        channel.basicConsume(QUEUE_NAME,false,consumer);
    }

    public static void main(String[] args) throws KeyManagementException, TimeoutException, NoSuchAlgorithmException, IOException, URISyntaxException {
        HelloWorldRec.recMsg();
    }
}
